#include "CCL_cpu.h"
using namespace std;
using std::max;
using std::min;

void CCL::create(uchar4* img,int width,int height, int umbral){
	this->pixel = (bool*)calloc(width*height,sizeof(bool));
	this->etiquetados = (int*)calloc(width*height,sizeof(int));
	this->width=width;
	this->height=height;
	this->nueva=0;
	for(int i=0;i<height;i++){
		for(int j=0;j<width;j++){
			int index = i * width + j;
			int red = (int)(img[index].x);
			int green = (int)(img[index].y);
			int blue = (int)(img[index].z);
			if((((float)(red + green + blue))/3) >= umbral){
				pixel[width * i + j] = 1;
			}
			else{
				pixel[width * i+ j] = 0;
			}
			etiquetados[width * i + j]=0;
		}
	}
}
int CCL::nuevaEtiqueta(){
	this->nueva++;
	return this->nueva;
}
int CCL::getPixel(int i,int j){
	return this->pixel[i*this->width+j];
}
int CCL::getEtiquetados(int i,int j){
	return this->etiquetados[i*this->width+j];
}
void CCL::setPixel(int i,int j, int k){
	this->pixel[i*this->width+j]=k;
}
void CCL::setEtiquetados(int i,int j, int k){
	this->etiquetados[i*this->width+j]=k;
}

int* CCL::getEtiquetadosArray(){
	return this->etiquetados;
}

int CCL::minimo(int i, int j){
	int M=INT_MAX;
	for(int k=max(i-1,0); k<=min(i+1,height-1);k++){
		for(int v=max(j-1,0); v<=min(j+1,width-1);v++){
			if(this->getEtiquetados(k,v)!=0){
				M = min(M,this->getEtiquetados(k,v));
			}
		}
	}
	return M;
}
/*
 * iterative program without cuda
 * PRE:h_img!=NULL width!=0 height!=0
 * POS: matrix CCL
 */
int* CCL_cpu(uchar4* img,int width,int height, int umbral){
	CCL p;
	int* result=NULL;
	bool CAMBIO=true;
	int M=-1;
	p.create(img,width,height, umbral);
	for(int i=0;i<height;i++){
		for(int j=0;j<width;j++){

			if(p.getPixel(i,j)==1){
				p.setEtiquetados(i,j,i*width+j+1);
			}
			else{
				p.setEtiquetados(i,j,0);
			}
		}
	}
	while(CAMBIO){
		CAMBIO=false;
		for(int i=0;i<height;i++){
			for(int j=0;j<width;j++){
				if(p.getEtiquetados(i,j)!=0){
					M= p.minimo(i,j);
					if(M!=p.getEtiquetados(i,j)){
						CAMBIO=true;
					}
					p.setEtiquetados(i,j,M);
				}
			}
		}
		for(int i=height-1;i>=0;i--){
			for(int j=width-1;j>=0;j--){
				if(p.getEtiquetados(i,j)!=0){
					M= p.minimo(i,j);
					if(M!=p.getEtiquetados(i,j)){
						CAMBIO=true;
					}
					p.setEtiquetados(i,j,M);
				}
			}
		}
	}
/*	free(p.pixel);*/
/*	for(int i=0;i<height;i++){
		for(int j=0;j<width;j++){
			if(p.getPixel(i,j)==1)
				p.setEtiquetados(i,j,1);
			else
				p.setEtiquetados(i,j,0);
		}
	}*/

	result = p.getEtiquetadosArray();
	return result;
}
